package org.yw.service.impl;

import com.alibaba.fastjson.JSON;
import org.springframework.mail.MailSender;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.stereotype.Service;
import org.yw.dao.DmUserMapper;
import org.yw.dto.Dto;
import org.yw.pojo.DmLinkUser;
import org.yw.pojo.DmUser;
import org.yw.service.LoginService;
import org.yw.utils.DtoUtil;
import org.yw.utils.ErrorCode;
import org.yw.utils.MD5;
import org.yw.utils.RedisUtil;
import org.yw.vo.Token;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Created By YU WEI on 2020.09.07
 */
@Service
public class LoginServiceImpl implements LoginService {
    @Resource
    private DmUserMapper dmUserMapper;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private MailSender mailSender;
    @Resource
    private SimpleMailMessage simpleMailMessage;

    /**
     * 用户登陆
     * @param phone
     * @param password
     * @throws Exception
     */
    @Override
    public Dto doLogin(String phone, String password) throws Exception {
        //根据phone查找匹配得user
        DmUser dmuser = dmUserMapper.getDmUserByPhone(phone);
        //判断找到得user空否
        if (null==dmuser){
            return DtoUtil.returnFail("非法的用户名", ErrorCode.AUTH_ILLEGAL_USERCODE);
        }
        //判断密码一致
        if (!dmuser.getPassword().equals(MD5.getMd5(password,32))) {
            return DtoUtil.returnFail("密码不正确", ErrorCode.BIZ_PARAMETER_ERROR);
        }
        //生成token
        String token=makeToken(dmuser);
        //保存token到redis中
        redisUtil.setKey(token, JSON.toJSONString(dmuser));
        redisUtil.expire(token,30*60);
        //返回成功
        List<Object> list=new ArrayList<>();
        Token token1=new Token();
        token1.setToken(token);
        token1.setExtTime(30*60*1000);
        token1.setGenTime(Calendar.getInstance().getTimeInMillis());
        list.add(dmuser);
        list.add(token1);

        return DtoUtil.returnSuccess("登陆成功",list);

    }

    /**
     * 注册用户保存信息
     * @param
     * @return
     * @throws Exception
     */
    @Override
    public Dto register(String phone,String password,String vcode) throws Exception {
        if (!redisUtil.isExists(phone)){
            return DtoUtil.returnFail("验证码失效",ErrorCode.AUTH_PARAMETER_ERROR);
        }
        if (!vcode.equals(redisUtil.getValue(phone))){
            return DtoUtil.returnFail("验证码不正确",ErrorCode.AUTH_PARAMETER_ERROR);
        }
        DmUser user=new DmUser();
        user.setPassword(MD5.getMd5(password,32));
        user.setPhone(phone);
        user.setCreatedTime(new java.sql.Date(System.currentTimeMillis()));
        int i=dmUserMapper.addDmUser(user);
        if (i>0){
            return DtoUtil.returnSuccess();
        }
        return DtoUtil.returnFail("注册失败",ErrorCode.AUTH_UNKNOWN);
    }

    /**
     * 发送验证码
     * @param phone
     * @return
     * @throws Exception
     */
    @Override
    public Dto sendCode(String phone) throws Exception {
        if(isEmail(phone)) {
            if (redisUtil.isExists(phone)){
                return DtoUtil.returnFail("验证码未失效，请不要重复请求",ErrorCode.AUTH_REPLACEMENT_FAILED);
            }
            int code = MD5.getRandomCode();
            simpleMailMessage.setTo(phone);
            simpleMailMessage.setSubject("大觅网验证码");
            simpleMailMessage.setText("注册账号为:"+phone+"验证码为："+code+"");
            try {
                Runnable runnable=()->{
                    mailSender.send(simpleMailMessage);
                };
                new Thread(runnable).start();

            }catch (Exception e){
                throw new RuntimeException("验证码发送失败");
            }
            redisUtil.setKey(phone,code+"");
            redisUtil.expire(phone,300);
        }
        return DtoUtil.returnSuccess();
    }

    /**
     * 根据token查询用户个人信息
     * @param token
     * @return
     * @throws Exception
     */
    @Override
    public Dto queryUserInfoByToken(String token) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_PARAMETER_ERROR);
        }
        DmUser user=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        return DtoUtil.returnDataSuccess(user);
    }

    private boolean isEmail(String phone) {
        String regex="^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
        boolean flag = Pattern.compile(regex).matcher(phone).find();
        return flag;
    }

    /**
     * 更新用户信息
     * @param user
     * @return
     * @throws Exception
     */
    @Override
    public Dto modifyUserInfo(DmUser user) throws Exception {
        user.setUpdatedTime(new java.sql.Date(System.currentTimeMillis()));
        int i=dmUserMapper.updateUserInfo(user);
        if (i>0){
            return DtoUtil.returnSuccess();
        }
        return DtoUtil.returnFail("更新失败",ErrorCode.AUTH_UNKNOWN);
    }

    /**
     * 查询用户常用购票人
     * @param token
     * @return
     */
    @Override
    public Dto queryLinkUser(String token) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_TOKEN_INVALID);
        }
        DmUser user=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        List<DmLinkUser> list=dmUserMapper.getDmLinkUserListByDmUserId(user.getId());
        return DtoUtil.returnDataSuccess(list);
    }

    @Override
    public Dto addLinkUser(String token, DmLinkUser user) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_TOKEN_INVALID);
        }
        DmUser userLogin=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        user.setUserId(userLogin.getId());
        user.setCreatedTime(new java.sql.Date(System.currentTimeMillis()));
        int i=dmUserMapper.addLinkUser(user);
        if (i>0){
            return DtoUtil.returnSuccess();
        }
        return DtoUtil.returnFail("增加失败",ErrorCode.AUTH_UNKNOWN);
    }

    /**
     * 查看常用购票人是否存在
     * @param token
     * @param idCard
     * @return
     * @throws Exception
     */
    @Override
    public Dto queryLinkUserByIdCard(String token, String idCard) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_TOKEN_INVALID);
        }
        DmUser userLogin=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        int i=dmUserMapper.queryLinkUserByIdCard(idCard,userLogin.getId());
        if (i>0){
            return DtoUtil.returnFail("此购票人已经存在",ErrorCode.AUTH_PARAMETER_ERROR);
        }
        return DtoUtil.returnSuccess();
    }

    /**
     * 删除常用购票人
     * @param token
     * @param linkId
     * @return
     * @throws Exception
     */
    @Override
    public Dto deleteLinkUserById(String token, Long linkId) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_TOKEN_INVALID);
        }
        DmUser userLogin=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        int i=dmUserMapper.deleteDmLinkUser(userLogin.getId(),linkId);
        if (i>0){
            return DtoUtil.returnSuccess();
        }
        return DtoUtil.returnFail("删除失败",ErrorCode.AUTH_UNKNOWN);
    }

    @Override
    public Dto replaceToken(String token) throws Exception {
        if (!redisUtil.isExists(token)){
            return DtoUtil.returnFail("token非法，请重新登陆",ErrorCode.AUTH_TOKEN_INVALID);
        }
        long time = redisUtil.getTime(token);
        if (time>300){
            return DtoUtil.returnFail("token无需置换",ErrorCode.AUTH_REPLACEMENT_FAILED);
        }
        DmUser userLogin=JSON.parseObject(redisUtil.getValue(token),DmUser.class);
        //生成新的token
        String newToken=makeToken(userLogin);
        Token token1=new Token();
        token1.setToken(newToken);
        token1.setExtTime(30*60*1000);
        token1.setGenTime(Calendar.getInstance().getTimeInMillis());
        List<Object> list=new ArrayList<>();
        list.add(userLogin);
        list.add(token1);
        return DtoUtil.returnSuccess("token置换成功",list);
    }

    /**
     * 验证phone是否可用
     * @param phone
     * @return
     * @throws Exception
     */
    @Override
    public Dto checkPhone(String phone) throws Exception {
        DmUser user = dmUserMapper.getDmUserByPhone(phone);
        if (user != null) {
            return DtoUtil.returnFail("用户名已存在", ErrorCode.AUTH_USER_ALREADY_EXISTS);
        }
        return DtoUtil.returnSuccess();
    }
    /**
     * 生成token
     * @param user
     * @return
     */
    private String makeToken(DmUser user) {
        StringBuffer token=new StringBuffer("token:PC-");
        //用户名
        token.append(MD5.getMd5(user.getPhone(),32)+"-");
        //用户Id
        token.append(user.getId()+"-");
        //创建时间
        token.append(new SimpleDateFormat("yyyyMMddHHmmss").format(new Date())+"-");
        //密码
        token.append(MD5.getMd5(user.getPassword(),6));
        //返回
        return token.toString();
    }
}
